//
// Created by hamlet on 2022/1/5.
//

#include "tianqiaccesser.h"
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QSettings>
#include <QTimer>

TianqiAccesser::TianqiAccesser(QObject *parent) :
        QObject(parent), m_settings(nullptr),
        m_manager(new QNetworkAccessManager(this)), m_timer(new QTimer(this)),
        m_method{}, m_sentRequestTimes{0}, m_settingsRemaining{0} {
    qRegisterMetaType<TianqiMethod>();
    qRegisterMetaType<MethodHefeng>();
    qRegisterMetaType<MethodTianqiServer>();
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
    qRegisterMetaTypeStreamOperators<TianqiMethod>();
    qRegisterMetaTypeStreamOperators<MethodHefeng>();
    qRegisterMetaTypeStreamOperators<MethodTianqiServer>();
#endif

    connect(m_timer, &QTimer::timeout, this, &TianqiAccesser::requestData);
    connect(m_manager, &QNetworkAccessManager::finished, this, &TianqiAccesser::processData);

    m_timer->setInterval(TIME_INTERVAL);
    m_timer->setTimerType(Qt::VeryCoarseTimer);
    m_timer->start();

    readSettings();
}

TianqiAccesser::~TianqiAccesser() = default;

void TianqiAccesser::readSettings() {
    setSettingsEnabled(true);
    m_method = m_settings->value("method").value<TianqiMethod>();
    qDebug() << "Read Settings\n" << m_method;
    m_methodData = m_settings->value("data");
}

void TianqiAccesser::writeSettings(TianqiMethod method, QVariant method_data) {
    setSettingsEnabled(true);
    m_method = method;
    qDebug() << "Write Settings\n" << m_method;
    m_methodData = qMove(method_data);
    m_settings->setValue("method", QVariant::fromValue(m_method));
    m_settings->setValue("data", m_methodData);
}

void TianqiAccesser::requestData() {
    qDebug() << "Requesting Tianqi data from Internet...";
    m_sentRequestTimes = 0;
    switch (m_method) {
        case TianqiMethod::Hefeng: {
            auto data = m_methodData.value<MethodHefeng>();
            auto url = QString("https://devapi.qweather.com/v7/weather/now?location=%1&key=%2")
                    .arg(data.location, data.key);
            sendRequest(url);

            url = QString("https://devapi.qweather.com/v7/air/now?location=%1&key=%2")
                    .arg(data.location, data.key);
            sendRequest(url);
            break;
        }
        case TianqiMethod::TianqiServer:
            break;
    }
    m_timer->start();

    // 释放settingsDialog以减少内存占用
    if (m_settingsRemaining) --m_settingsRemaining;
    else {
        setSettingsEnabled(false);
        emit sign_freeMemory();
    }
}

void TianqiAccesser::sendRequest(const QString &url) {
    qDebug() << "GET" << url;
    m_manager->get(QNetworkRequest(QUrl(url)));
    ++m_sentRequestTimes;
}

void TianqiAccesser::processData(QNetworkReply *reply) {
    qDebug() << "request received";
    bool success = false;
    auto json = QJsonDocument::fromJson(reply->readAll()).object();
    switch (m_method) {
        case TianqiMethod::Hefeng: {
            if (json["code"].toString() == "200") {
                success = true;
                auto now = json["now"].toObject();
                if (now.contains("aqi"))
                    m_data.aqi = now["aqi"].toString().toInt();
                if (now.contains("category"))
                    m_data.category = now["category"].toString();
                if (now.contains("temp"))
                    m_data.temp = now["temp"].toString().toInt();
                if (now.contains("text"))
                    m_data.text = now["text"].toString();
                if (now.contains("icon"))
                    m_data.icon = now["icon"].toString();
                m_timer->setInterval(TIME_STEP);
            } else {
                m_timer->setInterval(TIME_INTERVAL);
            }
            break;
        }
        case TianqiMethod::TianqiServer:
            break;
    }
    if (success) {  // 判断是否已经接受到发出数量的响应
        if (m_sentRequestTimes) --m_sentRequestTimes;
        if (!m_sentRequestTimes) {
            emit sign_needUpdate();
            qDebug() << "Request Success";
        }
    }
    reply->deleteLater();
}

void TianqiAccesser::restartCaching() {
    m_settingsRemaining = TianqiAccesser::CACHE_TIMES;
}

const TianqiData &TianqiAccesser::getData() const {
    return m_data;
}

void TianqiAccesser::setSettingsEnabled(bool state) {
    if (state) {
        if (!m_settings) {
            qDebug() << "Allocate new QSettings.";
            m_settings = new QSettings(this);
            restartCaching();
        }
    } else {
        if (m_settings) {
            qDebug() << "Delete QSettings.";
            m_settings->deleteLater();
            m_settings = nullptr;
        }
    }
}

TianqiMethod TianqiAccesser::getMethod() const {
    return m_method;
}

const QVariant &TianqiAccesser::getMethodData() const {
    return m_methodData;
}

void TianqiAccesser::requestDataAndCache() {
    requestData();
    restartCaching();
}
